var Request = new Class({

 //继承Chain,Events和Options的接口实现
 Implements: [Chain, Events, Options],

 options: {
  /*onRequest: $empty, //开始事件
  onSuccess: $empty,  //成功事件
  onFailure: $empty,  //失败事件
  onException: $empty,*/ //异常事件
  url: '',    //Ajax请求的地址
  data: '',    //Ajax提交的地址
  headers: {    //Ajax请求的HTTP头数据
   //来源信息
   'X-Requested-With': 'XMLHttpRequest',
   //接受的内容类型
   'Accept': 'text/javascrīpt, text/html, application/xml, text/xml, */*'
  },
  //是否异步请求
  async: true,
  //提交方式
  method: 'post',
  //多次请求冲突时的处理方式
  link: 'ignore',
  //判断状态成功的方法
  isSuccess: null,
  //判断状态成功的方法
  emulation: true,
  //是否使用url编码
  urlEncoded: true,
  //POST请求时使用的编码
  encoding: 'utf-8',
  //动态执行字符脚本
  evalscrīpts: false,
  //动态执行返回字符脚本
  evalResponse: false
 },

 //构造函数
 initialize: function(options){
  //使用浏览器特性创建一个XmlHttpRequest对象
  this.xhr = new Browser.Request();
  this.setOptions(options);
  //判断状态成功的方法，如果参数中不提供，使用默认方法
  this.options.isSuccess = this.options.isSuccess || this.isSuccess;
  this.headers = new Hash(this.options.headers);
 },

 onStateChange: function(){
  //如果状态码不等于4或者没有正执行的请求，直接返回
  if (this.xhr.readyState != 4 || !this.running) return;
  //设置标记
  this.running = false;
  //初始化状态码
  this.status = 0;
  //设置状态码
  $try(function(){
   this.status = this.xhr.status;
  }.bind(this));
  //如果状态码显示请求成功
  if (this.options.isSuccess.call(this, this.status)){
   //提取响应数据
   this.response = {text: this.xhr.responseText, xml: this.xhr.responseXML};
   //请求成功
   this.success(this.response.text, this.response.xml);
  } else {
   //响应数据全为null
   this.response = {text: null, xml: null};
   //请求失败
   this.failure();
  }
  //置空状态改变事件监听
  this.xhr.onreadystatechange = $empty;
 },

 //判断请求状态是否成功
 isSuccess: function(){
  //状态码大于等于200小于300时为成功
  return ((this.status >= 200) && (this.status < 300));
 },

 //处理返回字符中包含的脚本
 processscrīpts: function(text){
  //如果返回字符为纯脚本，直接解释执行
  if (this.options.evalResponse || (/(ecma|java)scrīpt/).test(this.getHeader('Content-type'))) return $exec(text);
  //混合字符时过滤出脚本，根据配置参数是否执行包含脚本
  return text.stripscrīpts(this.options.evalscrīpts);
 },

 //请求成功
 success: function(text, xml){
  //触发事件
  this.onSuccess(this.processscrīpts(text), xml);
 },
 
 //触发请求成功事件
 onSuccess: function(){
  //同时触发请求完成和请求成功事件
  this.fireEvent('onComplete', arguments).fireEvent('onSuccess', arguments).callChain();
 },
 
 //请求失败
 failure: function(){
  //触发事件
  this.onFailure();
 },

 //触发请求失败事件
 onFailure: function(){
  //同时触发请求完成和请求失败事件
  this.fireEvent('onComplete').fireEvent('onFailure', this.xhr);
 },

 //设置请求的HTTP头部数据
 setHeader: function(name, value){
  this.headers.set(name, value);
  return this;
 },

 //获取响应的HTTP头部数据
 getHeader: function(name){
  return $try(function(){
   return this.xhr.getResponseHeader(name);
  }.bind(this));
 },

 //检查约束，类似Fx的同名方法
 check: function(){
  //如果请求线程没有在运行中，返回真允许运行当前线程的请求
  if (!this.running) return true;
  //如果当前有正运行的请求线程
  switch (this.options.link){
   //配置了link参数为cancel时，直接取消正执行的线程，启用新线程
   case 'cancel': this.cancel(); return true;
   //等待当前线程执行完成再执行新线程
   case 'chain': this.chain(this.send.bind(this, arguments)); return false;
  }
  return false;
 },

 //发送请求
 send: function(options){
  //检查约束
  if (!this.check(options)) return this;
  //设置标记
  this.running = true;
  
  //根据参数类型处理
  var type = $type(options);
  if (type == 'string' || type == 'element') ōptions = {data: options};

  //实现更灵活的使用,可以将配置参数延后在send时
  var ōld = this.options;
  options = $extend({data: old.data, url: old.url, method: old.method}, options);
  var data = options.data, url = options.url, method = options.method;

  //不同类型的处理
  switch ($type(data)){
   //如果是HTML Element,读取它的值,并根据name值构成name=value的名值对
   case 'element': data = $(data).toQueryString(); break;
   case 'object': case 'hash': data = Hash.toQueryString(data);
  }

  //put和delete提交方式时的处理,因为Ajax不支持put和delete,所以通过添加一个_method给后台处理
  if (this.options.emulation && ['put', 'delete'].contains(method)){
   var _method = '_method=' + method;
   data = (data) ? _method + '&' + data : _method;
   method = 'post';
  }

  //POST方式指定编码时的处理,需要设置HTTP头部信息
  if (this.options.urlEncoded && method == 'post'){
   var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
   this.headers.set('Content-type', 'application/x-www-form-urlencoded' + encoding);
  }

  //GET方式时的处理,直接将提交的数据加在请求地址后面
  if (data && method == 'get'){
   //判断请求地址中有否包含问号
   url = url + (url.contains('?') ? '&' : '?') + data;
   data = null;
  }

  //打开请求端口,注意以下代码中xhr对象的方法的执行顺序
  this.xhr.open(method.toUpperCase(), url, this.options.async);

  //监听请求的响应状态更改事件
  this.xhr.onreadystatechange = this.onStateChange.bind(this);

  //设置所有HTTP头部信息
  this.headers.each(function(value, key){
   if (!$try(function(){
    this.xhr.setRequestHeader(key, value);
    return true;
   //出错时触发异常事件
   }.bind(this))) this.fireEvent('onException', [key, value]);
  }, this);

  //触发onRequest事件
  this.fireEvent('onRequest');
  //发送数据
  this.xhr.send(data);
  //如果是同步执行,不需要事件监听,直接进到状态处理方法
  if (!this.options.async) this.onStateChange();
  return this;
 },

 //取消请求
 cancel: function(){
  //如果没有正运行的线程，不必操作，直接返回
  if (!this.running) return this;
  //设置标记
  this.running = false;
  //中止请求
  this.xhr.abort();
  //置状态改变监听为空
  this.xhr.onreadystatechange = $empty;
  //创建新请求线程
  this.xhr = new Browser.Request();
  //触发onCancel事件
  this.fireEvent('onCancel');
  return this;
 }

});

//就地执行的匿名函数
(function(){
//HTTP的方法处理
var methods = {};
//处理用于Request继承实现的方法
['get', 'post', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){
 methods[method] = function(){
  //优先处理参数中字符类型的为请求地址,另一个有定义的参数为提交数据
  var params = Array.link(arguments, {url: String.type, data: $defined});
  //最终仍需要通过调用send方法执行
  return this.send($extend(params, {method: method.toLowerCase()}));
 };
});
/*
扩展实现,现在可以使用Request.get,Request.put之类的方法了,并且方法名不区分大小写,如:
Request.get('http://wfsr.net/action.aspx', 'id=1');
*/
Request.implement(methods);

})();

//单件模式,根据Request为Element实现的扩展
Element.Properties.send = {
 //setter
 set: function(options){
  //先从临时对象取实例
  var send = this.retrieve('send');
  //如果存在,取消执行
  if (send) send.cancel();
  //删除缓存的Request实例,缓存配置参数
  return this.eliminate('send').store('send:options', $extend({
   data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action')
  }, options));
 },

 //getter
 get: function(options){
  //如果提供了配置参数并且未存在实例
  if (options || !this.retrieve('send')){
   //如果没有缓存配置参数,调用setter缓存
   if (options || !this.retrieve('send:options')) this.set('send', options);
   //根据缓存参数,缓存Request实例
   this.store('send', new Request(this.retrieve('send:options')));
  }
  //返回缓存中的实例
  return this.retrieve('send');
 }

};

//Element的send方法
Element.implement({
 //Element可以直接执行send方法实现Ajax请求了
 send: function(url){
  //读取缓存中的Request实例
  var sender = this.get('send');
  //发送请求,Request的配置参数需要单独设置
  sender.send({data: this, url: url || sender.options.url});
  return this;
 }

});